package com.lz.sports.ui.checkmodel

import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.graphics.Rect
import android.graphics.SurfaceTexture
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.TextureView
import android.view.View
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.jeremyliao.liveeventbus.LiveEventBus
import com.lz.helper.CameraHelper
import com.lz.helper.HelperConfig
import com.lz.helper.camera.CameraParameter
import com.lz.helper.camera.CameraView
import com.lz.helper.camera.DrawHelper
import com.lz.helper.camera.DrawInfo
import com.lz.helper.face.*
import com.lz.helper.idcard.IDCardInfo
import com.lz.library.dialog.BaseDialogFragment
import com.lz.library.extension.click
import com.lz.sports.R
import com.lz.sports.bean.Examinee
import com.lz.sports.databinding.DialogFaceIdentifyBinding
import com.lz.sports.utils.ToastUtils
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

class FaceIdentifyDialog : BaseDialogFragment<DialogFaceIdentifyBinding>(),
    CameraView.PreviewCallback, TextureView.SurfaceTextureListener, CameraHelper.CameraCallback,
    FeatureRequest.Callback {

    companion object {

        val handler = Handler(Looper.getMainLooper())

        fun show(
            activity: FragmentActivity,
            examinee: Examinee, idCardInfo: IDCardInfo,
            type: Int, examThreshold: Float, idCardThreshold: Float
        ): FaceIdentifyDialog {
            val dialog = FaceIdentifyDialog().also {
                it.arguments = Bundle().apply {
                    putParcelable("examinee", examinee)
                    putParcelable("idCardInfo", idCardInfo)
                    putInt("type", type)
                    putFloat("examThreshold", examThreshold)
                    putFloat("idCardThreshold", idCardThreshold)
                }
            }
            dialog.setFrom(true)
            dialog.show(activity.supportFragmentManager)
            return dialog
        }
    }

    private val parameter = CameraParameter.def()

    private var drawHelper: DrawHelper? = null

    //考生信息
    private lateinit var examinee: Examinee
    private lateinit var idCardInfo: IDCardInfo

    //验证类型
    private var type: Int = 0
    private var examThreshold: Float = 0f
    private var idCardThreshold: Float = 0f

    private var scaleX = 0f
    private var scaleY = 0f

    private var hasResume = false

    private val helper by lazy {
        val w: Int
        val h: Int
        //如果流数据做了直角旋转，则必然导致宽高互换
        //如果流数据做了直角旋转，则必然导致宽高互换
        if (parameter.rotation == 90 || parameter.rotation == 270) {
            w = parameter.resolution[1]
            h = parameter.resolution[0]
        } else {
            w = parameter.resolution[0]
            h = parameter.resolution[1]
        }
        CameraHelper(w, h, this)
    }

    override fun getLayoutRes(): Int = R.layout.dialog_face_identify

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomDialog(requireContext(), false)

    @Suppress("DEPRECATION")
    override fun onAttach(context: Context) {
        super.onAttach(context)
        examinee = arguments!!.getParcelable("examinee")!!
        idCardInfo = arguments!!.getParcelable("idCardInfo")!!
        type = arguments!!.getInt("type")
        examThreshold = arguments!!.getFloat("examThreshold")
        idCardThreshold = arguments!!.getFloat("idCardThreshold")
    }

    override fun initData(v: View, savedState: Bundle?) {
        lifecycleScope.launch {
            arrayOf(binding.ivBack).click().collect { dismiss() }
        }
        initPreview()
    }

    override fun onResume() {
        super.onResume()
        hasResume = true
        binding.cvCamera.openCamera()
        helper.restart()
    }

    override fun onPause() {
        super.onPause()
        hasResume = false
        binding.cvCamera.releaseCamera()
        helper.pause()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        helper.quit()
    }

    private fun initPreview() {
        if (HelperConfig.isLYTDFlat()) parameter.setBackCamera() else parameter.setFrontCamera()
        binding.cvCamera.setParameter(parameter)
        binding.cvCamera.setPreviewCallback(this)
        binding.cvCamera.surfaceTextureListener = this
        helper.start()

        val examBitmap = loadBitmap(examinee.examPhotoFile())
        if (examBitmap == null) {
            ToastUtils.showMyToast(R.string.examineePhotoNone, Toast.LENGTH_SHORT)
            return
        }
        val idCardBitmap = idCardInfo.photoBitmap()
        if (idCardBitmap == null) {
            ToastUtils.showMyToast(R.string.idCardPhotoNone, Toast.LENGTH_SHORT)
            return
        }
        val examParams = FeatureParams(examBitmap, examThreshold)
        val idCardParams = FeatureParams(idCardBitmap, idCardThreshold)
        val request = when (type) {
            1 -> SingleRequest(type, null, examParams, handler, this)
            2 -> SingleRequest(type, idCardParams, null, handler, this)
            7 -> DoubleOrRequest(type, idCardParams, examParams, handler, this)
            12 -> DoubleAndRequest(type, idCardParams, examParams, handler, this)
            else -> null
        }
        if (request == null) {
            ToastUtils.showMyToast(R.string.faceIdentifySupport, Toast.LENGTH_SHORT)
            return
        }
        helper.pushFeatureRequest(request)
    }

    override fun onPreviewFrame(data: ByteArray, w: Int, h: Int) {
        helper.pushNvData(data)
    }

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, w: Int, h: Int) {
        scaleX = binding.cvCamera.width / 480f
        scaleY = binding.cvCamera.height / 640f
        drawHelper = DrawHelper(
            w, h, binding.cvCamera.width, binding.cvCamera.height,
            0, parameter.cameraId, false, false, false
        )
        binding.cvCamera.openCamera()
    }

    override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, w: Int, h: Int) {
    }

    override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean = false

    override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
    }

    override fun onDetectSuccess(detect: IntArray) {
        setDrawInfo(detect)
    }

    override fun onCameraError(status: Int) {
        if (status == CameraOperator.ERR_DETECT) {
            setDrawInfoNull()
        }
    }

    //检测到人脸页面上框出来
    private fun setDrawInfo(faceInfo: IntArray) {
        if (hasResume) {
//            LogUtils.i("drawInfo...")
            drawInfo.rect.set(
                (faceInfo[1] * scaleX).toInt(), (faceInfo[2] * scaleY).toInt(),
                (faceInfo[3] * scaleX).toInt(), (faceInfo[4] * scaleY).toInt()
            )
            drawHelper?.draw(binding.fvCamera, drawInfo)
        }
    }

    private val drawInfo = DrawInfo(Rect(), Color.GREEN, "")

    private fun setDrawInfoNull() {
        if (hasResume) {
            drawInfo.rect.set(0, 0, 0, 0)
            drawHelper?.draw(binding.fvCamera, drawInfo)
        }
    }

    override fun onFeatureError(type: Int, err: Int) {
        ToastUtils.showMyToast(R.string.faceIdentifyFail, Toast.LENGTH_SHORT)
        dismiss()
    }

    override fun onFeatureSuccess(
        type: Int,
        nvData: ByteArray,
        w: Int,
        h: Int,
        photoParams: FeatureParams?,
        examParams: FeatureParams?
    ) {
        LiveEventBus.get("FaceIdentifyDialog", FeatureResult::class.java)
            .post(FeatureResult(type, nvData, w, h, examinee, photoParams, examParams))
        ToastUtils.showMyToast(R.string.faceIdentifySuccess, Toast.LENGTH_SHORT)
        dismiss()
    }
}